/**
 * Created by Wang on 2018/7/16.
 */
if (console == null) {
    var console = {
        info: function () {
            var resultString = Array.prototype.slice.apply(arguments).join(',');
            Java.type("java.lang.System").out.println(resultString);
        }
    }
}
(function () {
    var myContext = Java.type("cn.edu.hit.kg.ScriptContext").getInstance();
    var Func = function (funcName, version) {
        version = version || "lastest";
        return myContext.getService(funcName);
    };

    var ConstValue = function (constName) {
        return myContext.getConstValue(constName);
    };

    var count = function (array) {
        return toRawArray(array).length;
    };

    var filter = function (array, predicte) {
        array = toRawArray(array);
        return array.filter(predicte);
    };

    var any = function (array, predicte) {
        array = toRawArray(array);
        return array.some(predicte);
    };

    var first = function (array) {
        if (isRawArray(array) && array.length > 0) {
            return array[0]
        }
        return null;
    };

    var compileMacro = function (codeString) {
        var regex = /`.*?`/;
        while (true) {
            var matched = codeString.match(regex);
            if (matched && matched.length > 0) {
                var expression = matched[0].slice(1, -1);
                var c_index = expression.indexOf(':');
                var catch_list = expression.substr(0, c_index);
                var func_body = expression.substr(c_index + 1);
                var func_code = "function (" + catch_list + "){return " + func_body + "}";
                codeString = codeString.replace(regex, func_code);
            } else {
                break;
            }
        }
        return codeString;
    };

    var jsExpression = function (values, params, funcName, signals, featureInstance) {
        signals = toRawArray(signals);
        funcName = compileMacro(funcName);
        var used_signals = [];

        console.info(funcName);

        var Feature = function (featureName, componentName) {
            var fs = signals.filter(function (feature) {
                if (feature.featureType != featureName) {
                    return false;
                }
                if (componentName != null) {
                    return feature.component != null && feature.component["name"] == componentName;
                } else {
                    return true;
                }
            });
            return fs.length > 0 ? fs[0] : null;
        };
        var FeatureValue = function (featureName, componentName) {
            var feature = Feature(featureName, componentName);
            console.info(feature);

            if (feature == null) {
                return null;
            } else {
                used_signals.push(feature);
                var fv = feature.value;
                if (isList(fv)) {
                    fv = toRawArray(fv);
                    if (fv.length > 0) {
                        return fv[0];
                    }
                } else {
                    return fv;
                }
                return null;
            }
        };
        var F = Func, S = Feature, V = FeatureValue, C = ConstValue;
        var result = eval(funcName);

        console.info(result);

        if (result && featureInstance) {
            used_signals.forEach(function (f) {
                featureInstance.channelIds
                    .addAll(Java.type("cn.edu.hit.kg.SignalUtil").unzipSignalIdFromDocument(f.getSource()));
            });
            used_signals = [];
        }
        return result;
    };
    myContext.registService('jsExpression', '1.0.0', jsExpression);

    var Collectors = Java.type("java.util.stream.Collectors");
    var flatToJavaList = function (list) {
        if (isList(list)) {
            return toJavaList(list)
                .stream()
                .map(function (e) {
                    return flatToJavaList(e);
                })
                .collect(Collectors.toList());
        } else {
            return list;
        }
    };

    var combineExpression = function (expression, transferArg, config, data, data2) {
        data = toRawArray(data || []);
        data2 = toRawArray(data2 || []);

        var arg = null;
        try {
            arg = JSON.parse(transferArg);
        } catch (e) {
            console.info("特征" + config.getString("portId") + " 的参数格式有误！");
        }
        expression = compileMacro(expression);
        var result = eval(expression);
        if (isList(result)) {
            result = flatToJavaList(result);
        }
        return result;
    };
    myContext.registService('combineExpression', '1.0.0', combineExpression);
})();
